/*
	Class: MooUi
		Change checkboxes and radios
		
	Usage:
		Works with these types of fields :
		- radio, checkbox and select

	Parameters:
		imagePath - path to img folder, can be full address. ex: 'http://floor.ch/img/'
		form_id - The id of the form. By default 'mainform'.
		prefixClass - Prefix for the class and the images. ex: with 'nice_' -> nice_radio & nice_checkbox
		suffixClass - Class for activ element. ex: with '_activ' -> nice_radio_activ
		errorClass - Class to signal error.
		numberOfStates - Number of states for checkbox. Will be changeable in future versions
		transitionTime - Transition lenght for select
		selectMaxLines - Max lines in a select list (if bigger, add a scroll)
		
	Exemple:
		You can easilly skin different forms with different theme with something like this :
		
		(code)
		<script type="text/javascript">
			window.addEvent('domready', function() {
				var niceForm = new MooUi({
					'form_id': 'first',
					'prefixClass': 'nice_'
				});
				var niceForm2 = new MooUi({
					'form_id': 'second',
					'prefixClass': 'nice2_',
					'transitionTime': '1000'
				});
			});
		</script>
		(end code)
	
	About:
		formcheck.js v.1.0 for mootools v1.1 05 / 2007
		
		by Floor SA (http://www.floor.ch) MIT-style license
		
		Created by Luca Pillonel and David Mignot
	
	
	
		
		@include "/iframework-classes/_mootools_full/mootools.v1.11.js"
*/
var MooUi = new Class({
	options: {
		imagePath		: 'img/',
		form_id			: 'mainform',	//the target form id
		prefixClass		: 'nice_',		//Prefix for the inputs and the images(ex: nice_radio & nice_checkbox);
		suffixClass		: '_actif',
		errorClass		: 'error',
		selectSkinType	: '2',			// 1-> variable lenght, more difficult to change / 2->One input with one background-image, easy to manipulate
		numberOfStates	: 3,
		transitionTime	: 200,
		selectMaxLines	: 10,
		scrollPeriod	: 250,
		linesPerStep	: 5
	},
	
	/*
	Constructor: initialize
		Constructor
	*/
	initialize: function(options){
		this.setOptions(options);
		if(!$(this.options.form_id)){ return false;}
		this._build();
	},
	
	/*
	Method: _build
		Internal method
		
		Start all things
	*/
	_build: function(){
		this.classSelHover = this.options.prefixClass+"selectHover";
		this.form = $(this.options.form_id);
		this.form.selectOpened = false;
		this.radioArray = [];
		this._handleResize();
		this._preload();
		this._preventSubmit();
	},
	
	/*
	Method: _preload
		Internal method
		
		Get the size of the images
	*/
	_preload: function(){
		this.radio = new Image();
		this.radio.src = this.options.imagePath+this.options.prefixClass+"radio.gif";
		this.checkbox = new Image();
		this.checkbox.onload=function(){(function(){this._readForm(this.options.form_id);}.bind(this)).delay(10);}.bind(this);
		this.checkbox.src = this.options.imagePath+this.options.prefixClass+"checkbox.gif";
		return;
	},
	
	/*
	Method: _handleResize
		Internal method
		
		Fix for apple related 'difference'...
	*/
	_handleResize: function(el){
		window.addEvent('resize', function(){
			if(this.selectArray){
				this.selectArray.each(function(el){
					this._positionSelectContainer(el);
				}.bind(this));
			}
		}.bind(this));
	},
	
	/*
	Method: _readForm
		Internal method
		
		Look for the form(s) then call the method _replaceElement
		
	Parameters:
		form_id - Id of the form
	*/
	_readForm: function(form_id){
		this.selectArray = [];
		$ES('input', form_id).each(function(el){
			if (el.type == "radio" || el.type == "checkbox"){
				if(el.type == "radio")this.radioArray.push(el);
				this.replaceElement(el);
			}
		}.bind(this));
		$ES('select', form_id).each(function(el){
			this.replaceSelect(el);
			this.selectArray.push(el);
		}.bind(this));
	},
	
	/*
	Method: replaceSelect
		Internal method
		
		Replace select with styled divs
		
	Parameters:
		el - Html element
	*/
	replaceSelect: function(el){
		this._setOptionsSelect(el);
		
		// Create new elements
		this._createNewList(el);
		if(el.optionsHtml.length>this.options.selectMaxLines){el.maxHeight = true;}
		this._createNewSelect(el);
		this._createSelectDeco(el);
		
		// Inject new elements
		el.resultContainer = new Element('div', {'class' : this.options.prefixClass+"select_open"}).injectAfter(el.selectBody);
		el.listeUl.injectInside(el.slideDiv);
		el.slideDiv.injectInside(el.resultContainer);
		
		// Manage scroll need
		el.scroll = this._manageScroll(el);
		
		// Handle the new list
		this._positionSelectContainer(el);
		this._addEffect(el);
		
		// Hide the old select
		el.setProperty('disabled', true);
		el.setStyle('display', 'none');
	},
	
	/*
	Method: _setOptionsSelect
		Internal method
		
	Parameters:
		el - Select object
	*/
	_setOptionsSelect: function(el){
		el.selectField = 0;
		el.maxHeight = 0;
		el.scrollPos = 0;
		el.optionsTxt = [];
		el.optionList = [];
		
		el.Coordinates = el.getCoordinates();
		el.HoverClassEl = this.options.prefixClass+"selectHover";
		el.listeUl = new Element('ul').addClass('scrollUl');
		el.slideDiv = new Element('div');
		el.optionsHtml = $ES('option', el);
		el.styleClass = this.options.prefixClass+"select";
		if(this.options.selectSkinType == 2){
			el.styleClass = this.options.prefixClass+"select_simple";
		}
	},
	
	/*
	Method: _createNewSelect
		Internal method
		
	Parameters:
		el - Select object
	*/
	_createNewSelect: function(el){
		el.selectOpened = false;
		el.selectBody = new Element("input", {
			'value': el.optionsTxt[0],
			'class' : el.styleClass,
			'events':{
				// Add all the events
				'focus': function(){
					this.form.selectOpened = true;
				}.bind(this),
				'click': function(){
					this._toggleSlide(el, 0, 1);
				}.bind(this),
				'blur': function(){
					this.form.selectOpened = false;
					(function(){this._toggleSlide(el, 1, 1);}.bind(this)).delay(200);
				}.bind(this),
				'keydown': function(e){
					el.kevent = new Event(e);
					if(el.kevent.key == 'esc'){el.selectBody.fireEvent('click');}
					if(el.kevent.key == 'up'){this._previousLine(el);}
					if(el.kevent.key == 'down'){this._nextLine(el);}
					if(el.kevent.key == 'enter' || el.kevent.key == 13){
						this._selectHover(el);
						this._toggleSlide(el, 0, 1);
						return;
					}
				}.bind(this)
			}
		}).injectBefore(el).setProperty('readonly', true);
	},
	
	/*
	Method: _createSelectDeco
		Internal method
		
	Parameters:
		el - Select object
	*/
	_createSelectDeco: function(el){
		if(this.options.selectSkinType ==1)
		{
			// Left decoration
			if(!window.webkit){
				el.selectLeft = new Element("img",{
					'events':{
						'click': function(){
							el.selectBody.fireEvent('click');	
						}
					},
					'src': this.options.imagePath+'nice_select_left.gif',
					'left': el.Coordinates.left.toInt(),
					'top': el.Coordinates.top.toInt()
				}).addClass('nice_select_left').injectBefore(el.selectBody);
			}
			
			// Right decoration
			el.selectButton = new Element("img",{
				'events':{
					'click': function(){
						el.selectBody.focus();
						el.selectBody.fireEvent('click');	
					}
				},
				'src': this.options.imagePath+'nice_select_right.gif',
				'left': el.Coordinates.width.toInt()+el.Coordinates.left.toInt(),
				'top': el.Coordinates.top.toInt()
			}).addClass('nice_select_right').injectAfter(el.selectBody);
		} else {
			// Simple input here	
		}
	},
	
	/*
	Method: _createNewList
		Internal method
		
	Parameters:
		el - Select object
	*/
	_createNewList: function(el){
		// Create the new option list
		el.optionsHtml.each(function(le, n){
			var z = le.getText();
			el.optionsTxt.push(z);
			var li = new Element('li',{
				'events':{
					'click': function(){
						el.selectBody.fireEvent('click');
						el.optionsHtml[n].selected = 'true';
						el.selectField = n;
						el.selectBody.value = z;
						el.slideDiv.fX.toggle();
					},
					'mousemove': function(){
						this._hoverLine(li, el);
					}.bind(this)
				}
			}).setHTML(z).injectInside(el.listeUl);
			el.optionList.push(li);
		}.bind(this));
	},
	
	/*
	Method: _positionSelectContainer
		Internal method
		
	Parameters:
		el - Select object
	*/
	_positionSelectContainer: function(el){
		el.selectBody.Coordinates = el.selectBody.getCoordinates();
		el.resultContainer.setStyles({
			'position': 'absolute',
			'width': el.selectBody.Coordinates.width.toInt(),
			'left': el.selectBody.Coordinates.left.toInt(),
			'top': el.selectBody.Coordinates.top.toInt()+el.selectBody.Coordinates.height.toInt()
		});
		el.listeUl.setStyle('width', el.selectBody.Coordinates.width.toInt());
	},
	
	/*
	Method: _addEffect
		Internal method
		
	Parameters:
		object - Select object
	*/
	_addEffect: function(el){
		el.slideDiv.fX = new Fx.Slide(el.slideDiv, {
			duration: this.options.transitionTime, 
			wait: true, 
			transition: Fx.Transitions.Quart.easeOut,
			onComplete : function(){}
		}).hide();
		return el;
	},

	/*
	Method: _preventSubmit
		Internal method
		
		Fix for apple related 'difference'...
	*/
	_preventSubmit: function(el){
		this.form.addEvent('submit', function(e) {
			if (this.form.selectOpened == true) new Event(e).stop();
		}.bind(this))
	},

	/*
	Method: _toggleSlide
		Internal method
		
	Parameters:
		el - Select object
	*/
	_toggleSlide: function(el, hide, opened){
		this._closeSelects(el);
		// Prevent form submission onEnter
		if (opened == 0) {
			if(this.form.selectOpened == false) this.form.selectOpened = true;
			else this.form.selectOpened = false;
		}
		this._positionSelectContainer(el);
		if(hide == 0) el.slideDiv.fX.toggle();
		else el.slideDiv.fX.slideOut();
	},
	
	/*
	Method: _closeSelects
		Internal method
		
	Parameters:
		el - Select object
	*/
	_closeSelects: function(el){
		this.selectArray.each(function(le){
			if(el != le && le.slideDiv.fX.open == true){
				le.selectBody.fireEvent('click');
			}
		}.bind(this));
	},
	
	/*
	Method: _manageScroll
		Internal method
		
	Parameters:
		el - Select object
	*/
	_manageScroll: function(el){
		if(el.maxHeight != 0){
			el.scrollDiv = new Element("div");
			el.scrolFx = new Fx.Scroll(el.scrollDiv,{
				'wait': true,
				'transition': Fx.Transitions.linear,
				'duration': this.options.scrollPeriod
			});
			el.pScroll = new Element("div");
			el.listeUl.injectInside(el.scrollDiv);
			el.scrollDiv.injectInside(el.pScroll);
			el.pScroll.injectInside(el.slideDiv);
			el.scrollUp = new Element("div").addClass('nice_scroll_up').injectBefore(el.scrollDiv);
			el.scrollDown = new Element("div").addClass('nice_scroll_down').injectAfter(el.scrollDiv);
			
			el.scrollDiv.setStyle('height', 200);
			el.scrollDiv.setStyle('overflow', 'hidden');
			this._addScrollEvent(el);
		}
	},
	
	/*
	Method: _addScrollEvent
		Internal method
		
	Parameters:
		el - Select object
	*/
	_addScrollEvent: function(el){
		el.selectBody.addEvents({
			'mousewheel': function(e){
				el.mevent = new Event(e).stop();
				// Mousewheel UP
				if (el.mevent.wheel > 0) {
					this._scrollUp(el);
				}
				// Mousewheel UP
				if (el.mevent.wheel < 0) {
					this._scrollDown(el);
				}
			}.bind(this)
		});
		el.listeUl.addEvents({
			'mousewheel': function(e){
				el.mevent = new Event(e).stop();
				// Mousewheel UP
				if (el.mevent.wheel > 0) {
					this._scrollUp(el);
				}
				// Mousewheel UP
				if (el.mevent.wheel < 0) {
					this._scrollDown(el);
				}
			}.bind(this)
		});
		el.scrollUp.addEvents({
			'mouseenter': function(){
				el.interval = (function(){this._scrollUp(el);}.bind(this)).periodical(this.options.scrollPeriod);
			}.bind(this),
			'mouseout': function(){
				el.bigScroll.stop();
				$clear(el.interval);
			}.bind(this)
		})
		el.scrollDown.addEvents({
			'mousemove': function(){
				el.interval = (function(){this._scrollDown(el);}.bind(this)).periodical(this.options.scrollPeriod);
			}.bind(this),
			'mouseout': function(){
				el.bigScroll.stop();
				$clear(el.interval);
			}.bind(this)
		})
	},
	
	/*
	Method: _scrollUp
		Internal method
		
	Parameters:
		el - Select object
	*/
	_scrollUp: function(el){
		el.scrollPos -= this.options.linesPerStep;
		if(el.scrollPos < 0) el.scrollPos = 0;
		el.scrolFx.toElement(el.optionList[el.scrollPos]);
	},
	
	/*
	Method: _scrollDown
		Internal method
		
	Parameters:
		el - Select object
	*/
	_scrollDown: function(el){
		el.scrollPos += this.options.linesPerStep;
		if(el.scrollPos > el.optionList.length-1) el.scrollPos = el.optionList.length-(this.options.linesPerStep-1);
		el.scrolFx.toElement(el.optionList[el.scrollPos]);
	},
	
	/*
	Method: _hoverLine
		Internal method
		
	Parameters:
		li - line to apply the hover class
		ob - Select object
	*/
	_hoverLine: function(li, ob){
		var classEl = this.options.prefixClass+"selectHover";
		if(ob.selectEl) ob.selectEl.removeClass(classEl);
		ob.selectEl = li.addClass(classEl);
	},
	
	/*
	Method: _nextLine
		Internal method (used for keyboard input)
		
	Parameters:
		object - Select object
	*/
	_nextLine: function(ob){
		ob.selectField++;
		ob.scrollPos = ob.selectField;
		if(ob.selectField > ob.optionsTxt.length-1){ 
			ob.selectField = 0;
			this._selectLine(ob, ob.selectField);
		}else{ 
			this._selectLine(ob, ob.selectField);
		};
	},
	
	/*
	Method: _previousLine
		Internal method (used for keyboard input)
		
	Parameters:
		object - Select object
	*/
	_previousLine: function(ob){
		ob.selectField--;
		ob.scrollPos = ob.selectField;
		if(ob.selectField < 0 ){ 
			ob.selectField = ob.optionsTxt.length-1;
			this._selectLine(ob, ob.optionsTxt.length-1);
		}else{ 
			this._selectLine(ob, ob.selectField);
		};
	},
	
	/*
	Method: _selectLine
		Internal method (used for keyboard input)
		
	Parameters:
		object - Select object
	*/
	_selectLine: function(ob, n){
		if(ob.maxHeight != 0){
			ob.scrolFx.toElement(ob.optionList[n]);
		}
		this._hoverLine(ob.optionList[n], ob);
		ob.selectBody.value = ob.optionsTxt[n];
		ob.optionsHtml[n].selected = 'true';
	},
	
	/*
	Method: _selectHover
		Internal method. Make the hover line selected when 'enter' key is pressed
		
	Parameters:
		object - Select object
	*/
	_selectHover: function(ob){
		ob.optionList.each(function(el, n){
			if(el.hasClass(this.classSelHover)){
				ob.selectField = n;
				ob.scrollPos = ob.selectField;
				this._selectLine(ob, ob.selectField);
			}
		}.bind(this))
	},
	
	/*
	Method: replaceElement
		Internal method
		
		Replace radios and checkboxes with styled divs
		
	Parameters:
		el - Html element
	*/
	replaceElement: function(el){
		var w = 0; var h=0;
		if(el.type=="radio"){
			w = this.radio.width;
			h = (this.radio.height/this.options.numberOfStates);
		}else{
			w = this.checkbox.width;
			h = this.checkbox.height/this.options.numberOfStates;
		}
		this.transparentGif = new Element("img",{
			'src': this.options.imagePath+'1px.gif',
			'width': w,
			'height': h
		});
		
		var span = new Element("span", {
			'class' : this.options.prefixClass+el.type,
			'events':{
				'click': function(){this._changeStatus(el, 0)}.bind(this)
			}
		}).injectBefore(el);
			
		//OnChange update image	
		if(window.ie){
			el.addEvent('focus', function(){
				this._changeStatus(el, 1);
			}.bind(this));
		}else{
			el.addEvent('change', function(){
				this._changeStatus(el, 1);
			}.bind(this));
		}
		if(el.checked){
			var activClass = this.options.prefixClass+el.type+this.options.suffixClass;
			span.addClass(activClass);
		}
		this.transparentGif.injectInside(span);
		el.setStyle('display', 'none');
	},

	/*
	Method: _changeStatus
		Internal method
		
		Change the status of the input and change the image of the span
		
	Parameters:
		el - Html input element
	*/
	_changeStatus: function(el, original){
		var activClass = this.options.prefixClass+el.type+this.options.suffixClass;
		if(el.type == "radio"){
			this.radioArray.each(function(le){
				if(el.getAttribute('name') == le.getAttribute('name') && el != le){
					$(le).getPrevious().removeClass(activClass);
				}
			}.bind(this));
			el.getPrevious().addClass(activClass);
			el.checked = true;
		} else{
			if(original == 0){
				if(el.checked != true){
					el.checked = true;
					el.getPrevious().addClass(activClass);
				}else{
					el.getPrevious().removeClass(activClass);
					el.checked = false;
				}
			}else{
				if(el.checked == true)
					el.getPrevious().addClass(activClass);
				else
					el.getPrevious().removeClass(activClass);
				
			}
		}
	}
});
MooUi.implement(new Options);